/*
 * ZipArchive.h
 *
 *  Created on: 2011-7-9
 *      Author: gexiao
 */
/*
 * Read-only access to Zip archives,with minimal heap allocation.
 */
#ifndef ZIPARCHIVE_H_
#define ZIPARCHIVE_H_
#include "SysUtil.h"
#include "DexFile.h"

#include <stdbool.h>
#include <sys/types.h>
/*
 * Trivial typedef to ensure that ZipEntry is not treated as a simple
 * integer. We use NULL to indicate an invalid value.
 */
typedef void* ZipEntry;

/*
 * One entry in the hash table.
 */
typedef struct ZipHashEntry {
	const char* name;
	unsigned short nameLen;
} ZipHashEntry;

/*
 * Read-only Zip archive.
 *
 * We want "open" and "find entry by name" to be fast operations, and we
 * want to use as little memory as possible. We memory-map the file,
 * and load a hash table with pointers to the filenames (which aren't
 * null-terminated). The other fields are at a fixed fields are at a fixed offset
 * from the filename,so we don't need to extract those (but we do need to byte-read
 * and endian-swap them every time we want them).
 *
 * To speed comparisons when doing a lookup by name, we could make the mapping
 * "private" (copy-on-write) and null-terminate the filenames after verifying
 * the record structure. However,this requires a private mapping of
 * every page that the Central Directory touches. Easier to tuck a copy
 * of the string length into the hash table entry.
 */

typedef struct ZipArchive {
	//open Zip archive
	int mFd;

	//mapped file
	off_t mDirectoryOffset;
	MemMapping mDirectoryMap;

	//number of entries in the Zip archive
	int mNumEntries;

	/*
	 * We know how many entries are in the Zip archive, so we can have a
	 * fixed-size hash table. We probe on collisions.
	 */
	int mHashTableSize;

	ZipHashEntry* mHashTable;
} ZipArchive;

//Zip compression methods we support
enum {
	kCompressStored = 0, //no compression
	kCompressDeflated = 8,
//standard deflate
};

/*
 * Open a Zip archive
 *
 * On success, returns 0 and populates "pArchive". Returns nonzero errno
 * value on failure.
 */
int dexZipOpenArchive(const char* fileName, ZipArchive* pArchive);

/*
 * Like dexZipOpenArchive, but takes a file descriptor open for reading
 * at the start of the file. The descriptor must be mappable (this does
 * not allow access to a stream).
 *
 * "debugFileName" will appear in error messages, but is not otherwise used.
 */
int dexZipPrepArchive(int fd, const char* debugFileName, ZipArchive* pArchive);

/*
 * Close archive,releasing resources associated with it.
 *
 * Depending on the implementation this could unmap pages used by classes
 * stored in a Jar. This should only be done after unloading classes.
 */
void dexZipCloseArchive(ZipArchive* pArchive);

/*
 * Retrieve one or more of the "interesting" fields. Non-NULL pointers
 * are filled in.
 */
int dexZipGetEntryInfo(const ZipArchive* pArchive, ZipEntry entry,
		int* pMethod, long* pUncompLen, long* pCompLen, off_t* pOffset,
		long* pModWhen, long* pCrc32);

/*
 * Return the archive's file descriptor.
 */DEX_INLINE int dexZipGetArchiveFd(const ZipArchive* pArchive) {
	return pArchive->mFd;
}

/*
 * Find an entry in the Zip archive, by name. Returns NULL if the entry
 * was not found.
 */
ZipEntry dexZipFindEntry(const ZipArchive* pArchive, const char* entryName);

/*
 * Simple accessors.
 */DEX_INLINE long dexGetZipEntryOffset(const ZipArchive* pArchive,
		const ZipEntry entry) {
	off_t val = 0;
	dexZipGetEntryInfo(pArchive, entry, NULL, NULL, NULL, &val, NULL, NULL);
	return val;
}

DEX_INLINE long dexGetZipEntryUncompLen(const ZipArchive* pArchive,
		const ZipEntry entry) {
	long val = 0;
	dexZipGetEntryInfo(pArchive, entry, NULL, &val, NULL, NULL, NULL, NULL);
	return val;
}

DEX_INLINE long dexGetZipEntryModTime(const ZipArchive* pArchive,
		const ZipEntry entry) {
	long val = 0;
	dexZipGetEntryInfo(pArchive, entry, NULL, NULL, NULL, NULL, &val, NULL);
	return val;
}

DEX_INLINE long dexGetZipEntryCrc32(const ZipArchive* pArchive,
		const ZipEntry entry) {
	long val = 0;
	dexZipGetEntryInfo(pArchive, entry, NULL, NULL, NULL, NULL, NULL, &val);
	return val;
}
#endif /* ZIPARCHIVE_H_ */

